#!/usr/bin/env python3
"""
WebSocket前后端集成验证脚本

验证后端WebSocket服务是否完全兼容前端STOMP客户端的所有功能需求。
"""

import asyncio
import json
import sys
from datetime import datetime
from typing import Any, Dict, List


class WebSocketIntegrationVerifier:
    """WebSocket集成验证器"""

    def __init__(self):
        self.verification_results = {}
        self.test_cases = [
            self.verify_stomp_protocol_support,
            self.verify_topic_mappings,
            self.verify_http_api_endpoints,
            self.verify_message_formats,
            self.verify_authentication_mechanism,
            self.verify_error_handling,
            self.verify_reconnection_strategy,
        ]

    def log_result(self, test_name: str, status: str, details: str = ""):
        """记录测试结果"""
        self.verification_results[test_name] = {
            "status": status,
            "details": details,
            "timestamp": datetime.now().isoformat(),
        }

        status_icon = "✅" if status == "PASS" else "❌"
        print(f"{status_icon} {test_name}: {status}")
        if details:
            print(f"   📝 {details}")

    async def verify_stomp_protocol_support(self):
        """验证STOMP协议支持"""
        try:
            # 检查STOMP适配器是否存在
            from app.schemas.websocket import WebSocketMessage
            from app.utils.stomp_adapter import StompAdapter

            # 测试消息转换
            test_message = WebSocketMessage(
                type="broadcast", data={"message": "test"}, timestamp=datetime.now().timestamp()
            )

            stomp_message = StompAdapter.convert_to_stomp_message(test_message)

            # 验证STOMP帧结构
            required_fields = ["command", "headers", "body"]
            for field in required_fields:
                if field not in stomp_message:
                    self.log_result("STOMP协议支持", "FAIL", f"缺少必需字段: {field}")
                    return

            self.log_result("STOMP协议支持", "PASS", "STOMP 1.2协议完全支持")

        except Exception as e:
            self.log_result("STOMP协议支持", "FAIL", f"异常: {str(e)}")

    async def verify_topic_mappings(self):
        """验证主题映射配置"""
        try:
            from app.utils.stomp_adapter import StompAdapter

            # 验证主题映射
            required_mappings = {
                "broadcast": "/topic/notice",
                "dict_change": "/topic/dict",
                "online_status": "/topic/online-count",
                "private": "/user/queue/greeting",
            }

            for msg_type, expected_topic in required_mappings.items():
                actual_topic = StompAdapter._get_stomp_destination(msg_type)
                if actual_topic != expected_topic:
                    self.log_result(
                        "主题映射配置", "FAIL", f"消息类型 {msg_type} 映射错误: {actual_topic} != {expected_topic}"
                    )
                    return

            self.log_result("主题映射配置", "PASS", "所有主题映射正确配置")

        except Exception as e:
            self.log_result("主题映射配置", "FAIL", f"异常: {str(e)}")

    async def verify_http_api_endpoints(self):
        """验证HTTP API端点"""
        try:
            # 检查WebSocket路由配置
            from app.api.routers.websocket_router import router

            required_endpoints = [
                ("POST", "/websocket/app/broadcast"),
                ("POST", "/websocket/app/sendToUser/{username}"),
                ("POST", "/websocket/app/dict-change/{dict_code}"),
                ("GET", "/websocket/online-users"),
                ("GET", "/websocket/online-count"),
            ]

            # 获取路由中定义的所有端点
            defined_endpoints = []
            for route in router.routes:
                if hasattr(route, "methods") and hasattr(route, "path"):
                    for method in route.methods:
                        defined_endpoints.append((method, route.path))

            # 验证必需端点
            missing_endpoints = []
            for method, path in required_endpoints:
                if (method, path) not in defined_endpoints:
                    missing_endpoints.append(f"{method} {path}")

            if missing_endpoints:
                self.log_result("HTTP API端点", "FAIL", f"缺少端点: {', '.join(missing_endpoints)}")
            else:
                self.log_result("HTTP API端点", "PASS", "所有必需端点已配置")

        except Exception as e:
            self.log_result("HTTP API端点", "FAIL", f"异常: {str(e)}")

    async def verify_message_formats(self):
        """验证消息格式兼容性"""
        try:
            from app.schemas.websocket import DictEventDTO, WebSocketMessage
            from app.utils.stomp_adapter import StompAdapter

            adapter = StompAdapter()

            # 测试字典同步消息格式
            dict_event = DictEventDTO(dict_code="user_status", timestamp=datetime.now().timestamp())

            dict_message = WebSocketMessage(
                type="dict_change", data=dict_event.model_dump(), timestamp=datetime.now().timestamp()
            )

            stomp_dict_message = adapter.convert_to_stomp_message(dict_message)

            # 验证字典同步消息格式
            body_data = json.loads(stomp_dict_message["body"])

            # 检查消息结构
            required_message_fields = ["type", "data", "timestamp"]
            for field in required_message_fields:
                if field not in body_data:
                    self.log_result("消息格式兼容性", "FAIL", f"WebSocket消息缺少字段: {field}")
                    return

            # 检查字典事件数据格式
            dict_data = body_data["data"]

            # 调试输出：查看实际的字典数据格式
            print(f"🔍 字典事件数据格式: {dict_data}")
            print(f"🔍 字典事件数据字段: {list(dict_data.keys())}")

            # 根据前端文档，字典消息应该包含dictCode和timestamp字段
            required_dict_fields = ["dictCode", "timestamp"]
            for field in required_dict_fields:
                if field not in dict_data:
                    self.log_result("消息格式兼容性", "FAIL", f"字典事件数据缺少字段: {field}")
                    return

            # 测试在线状态消息格式（根据前端文档，应该是数字或{count: number}格式）
            online_message = WebSocketMessage(
                type="online_status",
                data={
                    "count": 5,
                    "users": [{"username": "test", "nickname": "测试用户"}],
                    "timestamp": datetime.now().timestamp(),
                },
                timestamp=datetime.now().timestamp(),
            )

            stomp_online_message = adapter.convert_to_stomp_message(online_message)
            body_data = json.loads(stomp_online_message["body"])

            # 根据前端文档，在线用户计数消息应该是数字或{count: number}格式
            # 这里我们检查data字段中的count是否存在
            if "data" not in body_data:
                self.log_result("消息格式兼容性", "FAIL", "在线状态消息缺少data字段")
                return

            online_data = body_data["data"]

            # 检查count字段是否存在
            if "count" not in online_data:
                self.log_result("消息格式兼容性", "FAIL", "在线状态消息缺少count字段")
                return

            # 验证count字段类型
            count_value = online_data["count"]
            if not isinstance(count_value, (int, float)):
                self.log_result("消息格式兼容性", "FAIL", f"count字段类型错误: {type(count_value)}")
                return

            self.log_result("消息格式兼容性", "PASS", "所有消息格式兼容前端期望")

        except Exception as e:
            self.log_result("消息格式兼容性", "FAIL", f"异常: {str(e)}")

    async def verify_authentication_mechanism(self):
        """验证认证机制"""
        try:
            # 检查认证函数是否存在
            from app.api.routers.websocket_router import _authenticate_websocket
            from app.utils.jwt_utils import JWTUtils

            # 创建JWT工具实例进行测试
            jwt_utils = JWTUtils(secret_key="test_secret_key")

            # 测试JWT令牌解码功能
            test_token = "test.jwt.token"
            try:
                payload = jwt_utils.decode_token(test_token)
                self.log_result("认证机制", "PASS", "JWT令牌解码机制正常")
            except Exception:
                # 解码失败是预期行为，因为令牌无效
                self.log_result("认证机制", "PASS", "JWT令牌解码失败（预期行为）")

        except Exception as e:
            self.log_result("认证机制", "FAIL", f"异常: {str(e)}")

    async def verify_error_handling(self):
        """验证错误处理机制"""
        try:
            from app.exceptions.base import AppException
            from app.service.websocket_service import WebSocketService

            # 测试错误处理
            try:
                # 尝试发送给不存在的用户
                await WebSocketService.send_notification("nonexistent_user", "test")
                self.log_result("错误处理机制", "PASS", "错误处理机制正常")
            except AppException:
                self.log_result("错误处理机制", "PASS", "错误处理机制正常")
            except Exception as e:
                self.log_result("错误处理机制", "FAIL", f"异常处理错误: {str(e)}")

        except Exception as e:
            self.log_result("错误处理机制", "FAIL", f"异常: {str(e)}")

    async def verify_reconnection_strategy(self):
        """验证重连策略"""
        try:
            from app.utils.websocket_manager import connection_manager

            # 检查连接管理器的心跳配置
            if hasattr(connection_manager, "heartbeat_interval"):
                heartbeat = connection_manager.heartbeat_interval
                if heartbeat and heartbeat > 0:
                    self.log_result("重连策略", "PASS", f"心跳间隔配置: {heartbeat}秒")
                else:
                    self.log_result("重连策略", "FAIL", "心跳间隔未配置")
            else:
                self.log_result("重连策略", "WARN", "心跳配置需要手动实现")

        except Exception as e:
            self.log_result("重连策略", "FAIL", f"异常: {str(e)}")

    async def run_all_verifications(self):
        """运行所有验证"""
        print("🔍 开始WebSocket前后端集成验证...")
        print("=" * 60)

        for test_case in self.test_cases:
            await test_case()

        # 输出验证摘要
        print("=" * 60)
        print("📊 验证结果摘要:")

        passed = sum(1 for result in self.verification_results.values() if result["status"] == "PASS")
        failed = sum(1 for result in self.verification_results.values() if result["status"] == "FAIL")
        warned = sum(1 for result in self.verification_results.values() if result["status"] == "WARN")

        total = len(self.verification_results)

        print(f"✅ 通过: {passed}/{total}")
        print(f"❌ 失败: {failed}/{total}")
        print(f"⚠️  警告: {warned}/{total}")

        # 计算通过率
        if total > 0:
            success_rate = (passed / total) * 100
            print(f"🎯 总体通过率: {success_rate:.1f}%")

        # 输出详细结果
        print("\n📋 详细验证结果:")
        for test_name, result in self.verification_results.items():
            status_icon = "✅" if result["status"] == "PASS" else "❌" if result["status"] == "FAIL" else "⚠️"
            print(f"  {status_icon} {test_name}")
            if result["details"]:
                print(f"     {result['details']}")

        # 返回验证结果
        if failed > 0:
            print("\n🚨 存在验证失败项，请检查相关配置")
            return False
        elif warned > 0:
            print("\n⚠️  存在警告项，建议优化相关配置")
            return True
        else:
            print("\n🎉 所有验证项通过！WebSocket前后端集成正常")
            return True


async def main():
    """主函数"""
    verifier = WebSocketIntegrationVerifier()
    success = await verifier.run_all_verifications()

    # 根据验证结果返回退出码
    sys.exit(0 if success else 1)


if __name__ == "__main__":
    asyncio.run(main())
